package com.example.byd

import android.util.Log
import io.socket.client.IO
import io.socket.client.Socket
import org.json.JSONException
import org.json.JSONObject
import org.webrtc.IceCandidate
import org.webrtc.SessionDescription
import java.net.URISyntaxException
import java.security.KeyManagementException
import java.security.NoSuchAlgorithmException
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import java.util.*
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

/**
 * Created by chao on 2019/1/30.
 */
class SignalingClient private constructor() {
    private var socket: Socket? =null
    private val room = "OldPlace"
    private var callback: Callback? = null
    private val trustAll = arrayOf<TrustManager>(
        object : X509TrustManager {
            @Throws(CertificateException::class)
            override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
            }

            @Throws(CertificateException::class)
            override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
            }

            override fun getAcceptedIssuers(): Array<X509Certificate?> {
                return arrayOfNulls(0)
            }
        }
    )

    init {
        init()
    }

    fun setCallback(callback: Callback?) {
        this.callback = callback
    }

    private fun init() {
        try {
            val sslContext = SSLContext.getInstance("TLS")
            sslContext.init(null, trustAll, null)
            IO.setDefaultHostnameVerifier { hostname, session -> true }
            IO.setDefaultSSLContext(sslContext)
            val p = socket
            if(p == null) {
            socket=IO.socket("https://zhenyangyang.com:8080")
                Log.i("bydsong","开始进入房间1111")
                Log.i("bydsong","socket is ${socket}")
            }

            socket?.connect()
            socket?.emit("create or join", room)


            Log.i("bydsong","开始进入房间")
            socket?.on("created") { args ->
                Log.e("bydsong", " yangyang room created")
                callback!!.onCreateRoom()
            }
            socket?.on("full") { args -> Log.e("bydsong", " yangyang room full") }
            socket?.on("join") { args ->
                Log.e("bydsong", "peer joined")
                callback!!.onPeerJoined()
            }
            socket?.on("joined") { args ->
                Log.e("bydsong", "yangyang self joined")
                callback!!.onSelfJoined()
            }
            socket?.on("log") { args ->
                Log.e(
                    "bydsong",
                    "yangyang log call " + Arrays.toString(args)
                )
            }
            socket?.on("bye") { args ->
                Log.e("bydsong", "yangyang bye " + args.get(0))
                callback!!.onPeerLeave(args.get(0) as String)
            }
            socket?.on("message") { args ->
                Log.e("bydsong", "yangyang message " + Arrays.toString(args))
                val arg: Any = args.get(0)
                if (arg is String) {
                } else if (arg is JSONObject) {
                    val data = arg
                    val type = data.optString("type")
                    if ("offer" == type) {
                        callback!!.onOfferReceived(data)
                    } else if ("answer" == type) {
                        callback!!.onAnswerReceived(data)
                    } else if ("candidate" == type) {
                        callback!!.onIceCandidateReceived(data)
                    }
                }
            }
            Log.i("bydsong","初始化socket成功")
        } catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        } catch (e: KeyManagementException) {
            e.printStackTrace()
        } catch (e: URISyntaxException) {
            e.printStackTrace()
        }
    }

    fun sendIceCandidate(iceCandidate: IceCandidate) {
        val jo = JSONObject()
        try {
            jo.put("type", "candidate")
            jo.put("label", iceCandidate.sdpMLineIndex)
            jo.put("id", iceCandidate.sdpMid)
            jo.put("candidate", iceCandidate.sdp)
            socket?.emit("message", jo)
        } catch (e: JSONException) {
            e.printStackTrace()
        }
    }

    fun sendSessionDescription(sdp: SessionDescription) {
        val jo = JSONObject()
        try {
            jo.put("type", sdp.type.canonicalForm())
            jo.put("sdp", sdp.description)
            socket?.emit("message", jo)
        } catch (e: JSONException) {
            e.printStackTrace()
        }
    }

    interface Callback {
        fun onCreateRoom()
        fun onPeerJoined()
        fun onSelfJoined()
        fun onPeerLeave(msg: String?)
        fun onOfferReceived(data: JSONObject?)
        fun onAnswerReceived(data: JSONObject?)
        fun onIceCandidateReceived(data: JSONObject?)
    }

    companion object {
        private var instance: SignalingClient? = null
        fun get(): SignalingClient? {
            if (instance == null) {
                synchronized(SignalingClient::class.java) {
                    if (instance == null) {
                        instance = SignalingClient()
                    }
                }
            }
            return instance
        }
    }
}